package models

import (
	"time"
)

type Build struct {
	Model
	CID              int    `json:"c_id" form:"c_id"`                                                                                         // 计划id
	Number           int    `gorm:"column:number" db:"column:number" json:"number" form:"number"`                                             // 构建编号
	Result           string `gorm:"column:result" db:"column:result" json:"result" form:"result"`                                             // 构建结果
	QueueId          int    `gorm:"column:queue_id" db:"column:queue_id" json:"queue_id" form:"queue_id"`                                     // 构建时队列ID
	DisplayName      string `gorm:"column:display_name" db:"column:display_name" json:"display_name" form:"display_name"`                     // 构建名称
	FullName         string `gorm:"column:full_name" db:"column:full_name" json:"full_name" form:"full_name"`                                 // 构建全称
	Timestamp        int64  `gorm:"column:timestamp" db:"column:timestamp" json:"timestamp" form:"timestamp"`                                 // 构建开始时间毫秒
	Duration         int64  `gorm:"column:duration" db:"column:duration" json:"duration" form:"duration"`                                     // 构建时间毫秒
	Estimateddurati  int64  `gorm:"column:estimateddurati" db:"column:estimateddurati" json:"estimateddurati" form:"estimateddurati"`         // 预计构建时间毫秒
	StartUser        string `gorm:"column:start_user" db:"column:start_user" json:"start_user" form:"start_user"`                             // 启动构建的用户
	ShortDescription string `gorm:"column:short_description" db:"column:short_description" json:"short_description" form:"short_description"` // 操作描述
	RemoteURL        string `gorm:"column:remote_url" db:"column:remote_url" json:"remote_url" form:"remote_url"`                             // 远端仓库地址
	Type             int    `gorm:"column:type" db:"column:type" json:"type" form:"type"`                                                     // 构建类型 1 手动  2定时   3 webhook
	ImageTag         string `gorm:"column:image_tag" db:"column:image_tag" json:"image_tag" form:"image_tag"`                                 // 当前build出来的镜像tag
}

type BuildStage struct {
	Model
	BuildId     int    `gorm:"column:build_id" db:"column:build_id" json:"build_id" form:"build_id"`                 // 构建记录ID
	Name        string `gorm:"column:name" db:"column:name" json:"name" form:"name"`                                 // 记录名称
	Result      string `gorm:"column:result" db:"column:result" json:"result" form:"result"`                         // 构建记录状态
	Timestamp   int64  `gorm:"column:timestamp" db:"column:timestamp" json:"timestamp" form:"timestamp"`             // 构建开始时间 毫秒
	Duration    int64  `gorm:"column:duration" db:"column:duration" json:"duration" form:"duration"`                 // 构建时间 毫秒
	Number      int    `gorm:"column:number" db:"column:number" json:"number" form:"number"`                         // 构建记录编号
	FirstParent int    `gorm:"column:first_parent" db:"column:first_parent" json:"first_parent" form:"first_parent"` // 并行阶段的父id
	Type        string `gorm:"column:type" db:"column:type" json:"type" form:"type"`                                 // 步骤类型
	State       string `gorm:"column:state" db:"column:state" json:"state" form:"state"`                             // 辅助状态
}

type BuildStageInfo struct {
	Model
	BuildID   int    `gorm:"column:build_id" db:"column:build_id" json:"build_id" form:"build_id"`     // 构建记录ID
	StageID   int    `gorm:"column:stage_id" db:"column:stage_id" json:"stage_id" form:"stage_id"`     // 步骤ID
	Name      string `gorm:"column:name" db:"column:name" json:"name" form:"name"`                     // 步骤名称
	Result    string `gorm:"column:result" db:"column:result" json:"result" form:"result"`             // 步骤状态
	Timestamp int64  `gorm:"column:timestamp" db:"column:timestamp" json:"timestamp" form:"timestamp"` // 步骤开始时间 毫秒
	Duration  int64  `gorm:"column:duration" db:"column:duration" json:"duration" form:"duration"`     // 步骤构建时间 毫秒
	Number    int    `gorm:"column:number" db:"column:number" json:"number" form:"number"`             // 步骤编号
	Log       string `gorm:"column:log" db:"column:log" json:"log" form:"log"`                         // 步骤输出日志
}

type BuildOneResponse struct {
	CID              int                  `json:"c_id"`              // 构建计划ID
	CiName           string               `json:"ci_name"`           // 构建计划名称
	BuildNumber      int                  `json:"build_number"`      // 构建记录编号
	Result           string               `json:"result"`            // 构建结果
	Timestamp        int64                `json:"timestamp"`         // 触发时间
	Duration         int64                `json:"duration"`          // 总计持续时长
	RemoteURL        string               `json:"remote_url"`        // 仓库链接
	Branch           string               `json:"branch"`            // 仓库链接
	ShortDescription string               `json:"short_description"` // 构建触发信息
	Stages           []*BuildStageAndFlow `json:"stages"`            // 构建步骤
}

type BuildStageInfoResponse struct {
	BuildNumber      int                  `json:"build_number"`      // 构建记录编号
	ShortDescription string               `json:"short_description"` // 构建人
	Result           string               `json:"result"`            // 构建结果
	Timestamp        int64                `json:"timestamp"`         // 触发时间
	Duration         int64                `json:"duration"`          // 总计持续时长
	Stages           []*BuildStageAndFlow `json:"stages"`            // 构建步骤
}

type BuildStageAndFlow struct {
	BuildStage
	Flow []BuildStageInfo `json:"flow"`
}

type BuildStageSimple struct {
	BuildID int          `json:"build_id"`
	Stages  []BuildStage `json:"stages"`
}

type BuildDashboard struct {
	CID       int    `json:"c_id"`
	CName     string `json:"ci_name"`
	PID       int    `json:"project_id"`
	PName     string `json:"project_name"`
	BuildID   int    `json:"build_id"`
	Result    string `json:"result"`
	StartUser string `json:"start_user"`
	BuildType int    `json:"type"`
	StartTime int    `json:"start_time"`
	Duration  int64  `json:"duration"`
}

/**
*****************************************************************
******************************build******************************
*****************************************************************
 */

func GetBuild(number int, cid int) *Build {
	build := &Build{}
	db.Where("deleted_at = 0").
		Where("c_id = ?", cid).
		Where("number = ?", number).
		First(build)
	return build
}

func GetBuildByID(id int) *Build {
	build := &Build{}
	db.Where("deleted_at = 0").
		Where("id = ?", id).
		First(build)
	if build.ID == 0 {
		return nil
	}
	return build
}

func GetAllBuild(cid int) []*Build {
	builds := make([]*Build, 0)
	db.Model(&Build{}).Where("c_id = ?", cid).Where("deleted_at = 0").Find(&builds)
	return builds
}

func GetAllBuildNumber(cid int) []int {
	ids := make([]int, 0)
	db.Model(&Build{}).Where("c_id = ?", cid).Where("deleted_at = 0").Select("number").Find(&ids)
	return ids
}

func GetAllBuildPage(cid int, page int, pageSize int) ([]*Build, int) {
	builds := make([]*Build, 0, pageSize)
	var total int64
	db.Model(&Build{}).Where("c_id = ?", cid).Where("deleted_at = 0").Count(&total)
	db.Model(&Build{}).Where("c_id = ?", cid).Where("deleted_at = 0").
		Offset((page - 1) * pageSize).
		Limit(pageSize).
		Order("number desc").
		Find(&builds)
	return builds, int(total)
}

func GetBuildPageBetweenTime(start, end, page, pageSize int) ([]*Build, int) {
	builds := make([]*Build, 0)
	//db.Where("deleted_at = 0").Find(&builds)
	//for _, b := range builds {
	//	if ci := GetCIByID(b.CID); ci == nil {
	//		fmt.Println(111)
	//		db.Model(&Build{}).Where("id = ?", b.ID).Update("deleted_at", time.Now().Unix())
	//	}
	//}

	var total int64
	db.Model(&Build{}).Where("deleted_at = 0").Where("created_at BETWEEN ? AND ?", start, end).Count(&total)
	db.Where("deleted_at = 0").
		Where("created_at BETWEEN ? AND ?", start, end).
		Order("created_at desc").
		Offset((page - 1) * pageSize).
		Limit(pageSize).
		Find(&builds)
	return builds, int(total)
}

func GetCILastBuild(cid int) *Build {
	build := Build{}
	db.Table("devops_build").Where("c_id = ?", cid).Where("deleted_at = 0").Last(&build)
	if build.ID == 0 {
		return nil
	}
	return &build
}

func GetLastBuildNumber(cid int) int {
	build := Build{}
	db.Where("c_id = ?", cid).Last(&build)
	return build.Number
}

func CreateBuild(b *Build) error {
	return db.Create(b).Error
}

// 批量插入
func CreateBuilds(builds []Build) error {
	return db.Create(&builds).Error
}

func UpdateBuild(id int, b Build) error {
	return db.Model(&Build{}).Where("id = ?", id).Updates(&b).Error
}

func HardDeleteBuild(id int) error {
	return db.Where("id = ?", id).Delete(&Build{}).Error
}

func DeleteBuildWithOther(buildID int) error {
	tx := db.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()
	// 删除构建记录
	if err := tx.Model(&Build{}).Where("id = ?", buildID).Update("deleted_at", time.Now().Unix()).Error; err != nil {
		return err
	}
	// 删除步骤
	if err := tx.Where("build_id = ?", buildID).Delete(BuildStage{}).Error; err != nil {
		return err
	}
	// 删除步骤详情
	if err := tx.Where("build_id = ?", buildID).Delete(BuildStageInfo{}).Error; err != nil {
		return err
	}
	// 删除制品
	if err := tx.Where("build_id = ?", buildID).Delete(BuildArtifact{}).Error; err != nil {
		return err
	}
	return tx.Commit().Error
}

func GetStageByBuildIDAndFlows(buildId int) []*BuildStageAndFlow {
	buildStagesAndFlows := make([]*BuildStageAndFlow, 0)
	stages := GetBuildStages(buildId)
	for _, s := range stages {
		infos := GetBuildStageInfos(s.ID)
		buildStagesAndFlows = append(buildStagesAndFlows, &BuildStageAndFlow{s, infos})
	}
	return buildStagesAndFlows
}

/**
*****************************************************************
************************build stage******************************
*****************************************************************
 */

func GetBuildStageByID(id int) BuildStage {
	buildStage := BuildStage{}
	db.Where("id = ?", id).Where("deleted_at = 0").Find(&buildStage)
	return buildStage
}

func GetBuildStages(buildId int) []BuildStage {
	stages := make([]BuildStage, 0)
	db.Where("build_id = ?", buildId).Where("deleted_at = 0").Order("number").Find(&stages)
	return stages
}

func GetBuildStage(buildID int, number int) BuildStage {
	bs := BuildStage{}
	db.Where("build_id = ?", buildID).Where("number = ?", number).Where("deleted_at = 0").First(&bs)
	return bs
}

func CreateBuildStage(s *BuildStage) error {
	return db.Create(s).Error
}

func UpdateBuildStage(id int, s BuildStage) error {
	return db.Model(&BuildStage{}).Where("id = ?", id).Updates(&s).Error
}

func DeleteBuildStages(ids []int) error {
	return db.Where("id IN (?)", ids).Delete(&BuildStage{}).Error
}

/**
*****************************************************************
************************build stage info*************************
*****************************************************************
 */

func CreateBuildStageInfo(s *BuildStageInfo) error {
	return db.Create(s).Error
}

func GetBuildStageInfoByID(id int) BuildStageInfo {
	info := BuildStageInfo{}
	db.Where("id = ?", id).First(&info)
	return info
}

func GetBuildStageInfo(stageID int, number int) BuildStageInfo {
	info := BuildStageInfo{}
	db.Where("stage_id = ?", stageID).Where("number = ?", number).First(&info)
	return info
}

func GetBuildStageInfos(stageID int) []BuildStageInfo {
	infos := make([]BuildStageInfo, 0)
	db.Where("stage_id = ?", stageID).Find(&infos)
	return infos
}

func UpdateBuildStageInfo(id int, info BuildStageInfo) error {
	return db.Model(&BuildStageInfo{}).Where("id = ?", id).Updates(&info).Error
}
